package com.tianji.learning.task;

import cn.hutool.core.util.ObjectUtil;
import com.tianji.learning.domain.po.PointsBoard;
import com.tianji.learning.service.IPointsBoardSeasonService;
import com.tianji.learning.service.IPointsBoardService;
import com.tianji.learning.utils.TableNameContext;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.List;

import static com.tianji.common.constants.Constant.POINTS_BOARD_TABLE_NAME;
import static com.tianji.common.utils.DateUtils.DATE_SUFFIX_FORMATTER;
import static com.tianji.common.utils.DateUtils.DEFAULT_MONTH_FORMAT_COMPACT;
import static com.tianji.learning.constants.RedisConstants.POINTS_BOARD_KEY_PREFIX;

@Component
@RequiredArgsConstructor
public class PointsBoardPersistentTask {
    private final IPointsBoardSeasonService seasonService;
    private final IPointsBoardService boardService;
    private final RedisTemplate redisTemplate;

    @XxlJob("createTableJob")
    public void createTable() {
        // 1.获取上月时间
        LocalDateTime time = LocalDateTime.now().minusDays(1L);

        // 2.查询赛季ID
        Integer seasonId = seasonService.querySeasonIdByTime(time);

        // 3.创建表
        boardService.createTable(seasonId);

    }

    @XxlJob("savePointsBoard2DB")
    public void savePointsBoard2DB() {
        // 1.获取上月时间
        LocalDateTime time = LocalDateTime.now().minusDays(1L);

        // 2.查询赛季ID
        Integer seasonId = seasonService.querySeasonIdByTime(time);

        // 3.计算动态表名,存入ThreadLocal
        String tableName = POINTS_BOARD_TABLE_NAME + "_" + seasonId;
        TableNameContext.setTableName(tableName);

        // 当前实例的xxljob分片序号： 0  1  2
        int shardIndex = XxlJobHelper.getShardIndex();
        // xxljob总分片数，如 3
        int shardTotal = XxlJobHelper.getShardTotal();

        redisTemplate.opsForValue().set("shardTotal", shardTotal);
        // 4.查询Redis中上月榜单
        // 4.1 拼接key
        String key = POINTS_BOARD_KEY_PREFIX + time.format(DATE_SUFFIX_FORMATTER);
        // 4.2 分页查询榜单数据
        int pageNo = shardIndex + 1, pageSize = 1000;
        while (true) {
            List<PointsBoard> boardList = boardService.queryCurrentBoards(key, pageNo, pageSize);
            if (ObjectUtil.isEmpty(boardList)) {
                break;
            }

            // 5.将榜单数据存入数据库
            boardList.forEach(
                    board -> {
                        board.setId(board.getRank().longValue());
                        board.setRank(null);
                    }
            );
            boardService.saveBatch(boardList);
            pageNo += shardTotal;
        }
        // 6.清理ThreadLocal
        TableNameContext.remove();
        redisTemplate.opsForValue().increment("shardIndex");

    }

    @XxlJob("clearPointsBoardFromRedis")
    public void clearPointsBoardFromRedis() {
        Integer shardIndex = (Integer)redisTemplate.opsForValue().get("shardIndex");
        Integer shardTotal = (Integer)redisTemplate.opsForValue().get("shardTotal");
        if (ObjectUtil.notEqual(shardIndex, shardTotal)){
            return;
        }
        // 1.获取上月时间
        LocalDateTime time = LocalDateTime.now().minusDays(1L);

        // 2.拼接key
        String key = POINTS_BOARD_KEY_PREFIX + time.format(DATE_SUFFIX_FORMATTER);

        // 3.清理redis
        redisTemplate.unlink(key);
    }
}
